/**
 *@Time    : 2021/11/11 21:00
 *@Author  : Shuai Jhou
 *@File    : client
 *@Software: GoLand
 */

package main

import (
	"context"
	"fmt"
	"github.com/golang/protobuf/ptypes/timestamp"
	"go.zhoushuai.cn/go-programming-tour-book/grpc-pratice/middleware"
	. "go.zhoushuai.cn/go-programming-tour-book/grpc-pratice/services"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"io"
	"log"
	"time"
)

type AuthClient struct {
	AppKey    string
	AppSecret string
}

func (a *AuthClient) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	return map[string]string{"app_key": a.AppKey, "app_secret": a.AppSecret}, nil
}

func (a *AuthClient) RequireTransportSecurity() bool {
	return false
}

func main() {
	ctx := context.Background()
	clientConn, _ := GetClientConn(ctx, ":8081", 3)
	defer clientConn.Close()
	//ClientUserService(clientConn)
	//ClientOrderService(clientConn)
	ClientOrderService(clientConn)
	//ClientProdService(clientConn)
}

func GetClientConn(ctx context.Context, target string, model int32) (clientConn *grpc.ClientConn, err error) {
	var opts []grpc.DialOption
	auth := AuthClient{
		AppKey:    "go-programming-tour-book",
		AppSecret: "Jhou-Shuai",
	}
	opts = append(opts, grpc.WithPerRPCCredentials(&auth))

	if 2 == model {
		cred, err := credentials.NewClientTLSFromFile("../keys/ca.crt", "zhoushuai.cn")
		if err != nil {
			log.Fatal(err)
		}
		opts = append(opts, grpc.WithTransportCredentials(cred))
	} else {
		opts = append(opts, grpc.WithInsecure())
	}
	if 3 == model {
		// 超时控制（上下文）
		opts = append(opts, grpc.WithChainUnaryInterceptor(
			middleware.UnaryContextTimeout(),
		))
		// 超时控制（上下文）
		//opts = append(opts, grpc.WithChainStreamInterceptor(
		//	middleware.StreamContextTimeout(),
		//))

		// 重试操作
		//opts = append(opts, grpc.WithUnaryInterceptor(
		//	grpcRetry.UnaryClientInterceptor(
		//		grpcRetry.WithMax(2),
		//		grpcRetry.WithCodes(
		//			codes.Unknown,
		//			codes.Internal,
		//			codes.DeadlineExceeded,
		//		),
		//	),
		//))

		// 链路追踪
		opts = append(opts, grpc.WithChainUnaryInterceptor(
			middleware.ClientTracing(),
		))

		clientConn, err = grpc.DialContext(ctx, target, opts...)
	} else {
		clientConn, err = grpc.Dial(target, opts...)
	}
	return clientConn, err
}

func ClientProdService(conn *grpc.ClientConn) {
	prodClient := NewProdServiceClient(conn)
	//prodResult, err := prodClient.GetProdStock(context.Background(), &ProdRequest{ProdId: 12, ProdArea: ProdAreas_A})
	prodResult, err := prodClient.GetProdInfo(context.Background(), &ProdRequest{ProdId: 12})
	//prodResult, err := prodClient.GetProdStocks(context.Background(), &services.QuerySize{Size: 10})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(prodResult)
	//fmt.Println(prodResult.ProdStock)
	//fmt.Println(prodResult.ProdRes)
}

func ClientOrderService(conn *grpc.ClientConn) {
	ctx := context.Background()
	//newCtx := metadata.AppendToOutgoingContext(ctx, "JhouShuai", "I love YOU!")
	t := timestamp.Timestamp{Seconds: time.Now().Unix()}
	orderClient := NewOrderServiceClient(conn)
	orderResult, err := orderClient.NewOrder(ctx, &OrderRequest{
		OrderMain: &OrderMain{
			OrderId:    1001,
			OrderNo:    "NO.121212",
			OrderMoney: 99.8,
			OrderTime:  &t,
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(orderResult)
}

func ClientUserService(conn *grpc.ClientConn) {
	var i int32
	ctx := context.Background()
	userClient := NewUserServiceClient(conn)
	users := make([]*UserInfo, 0)
	for i = 1; i < 6; i++ {
		users = append(users, &UserInfo{UserId: i})
	}
	//userScoreList, err := userClient.GetUserScore(ctx, &UserScoreRequest{Users: users})
	userScoreList, err := userClient.GetUserScoreByServerStream(ctx, &UserScoreRequest{Users: users})
	if err != nil {
		log.Fatal(err)
	}
	for {
		resp, err := userScoreList.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(resp.Users)
		// go func  go 协程 处理
	}
	//fmt.Println(userScoreList.Users)
}
